﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using WordsReminder.Properties;
using SpeechLib;

namespace WordsReminder
{
    public partial class MainForm : Form
    {
        bool isMouseDown = false;
        Point startDragPosition;
        dbTableAdapters.WordsTableAdapter wordsTableAdapter;
        Random random = new Random();
        WordEntryCollection EntryList = new WordEntryCollection();
        WordEntry currentEntry;
        SpVoice voice;
        Thread suggestionThread;

        public MainForm()
        {
            InitializeComponent();
            wordsTableAdapter = new WordsReminder.dbTableAdapters.WordsTableAdapter();
            RefreshData();
            voice = new SpVoice();
        }


        private void MainForm_Load(object sender, EventArgs e)
        {
            this.Location = Settings.Default.FormLocation;
            this.Opacity = Settings.Default.FormOpacity / 100.0;
            AddNewWordPanel.Location = HeadControlsPanel.Location;
            AddNewWordPanel.Size = new Size(HeadControlsPanel.Width, HeadControlsPanel.Height + WordsPanel.Height);
            timerChangeWord.Interval = Settings.Default.TimerInterval;
            timerChangeWord.Start();
            GetRandomWord(null, null);
        }

        void RefreshData()
        {
            lock (wordsTableAdapter)
            {
                db.WordsDataTable remindingWordsTable = wordsTableAdapter.GetDataByRemainingType(true);
                EntryList.Clear();
                int rowsCount = remindingWordsTable.Rows.Count;
                for (int i = 0; i < rowsCount; i++)
                {
                    int rand = random.Next(rowsCount - i);
                    string word = (string)remindingWordsTable.Rows[rand]["Word"];
                    word = char.ToUpper(word[0]).ToString() + word.Substring(1);
                    EntryList.Add(word
                        , (string)remindingWordsTable.Rows[rand]["Meaning"]);
                    remindingWordsTable.Rows.RemoveAt(rand);
                }
                remindingWordsTable.Dispose();
            }
            currentEntry = EntryList[0];
        }

        private void AddNewWord(object sender, EventArgs e)
        {
            lock (wordsTableAdapter)
            {
                if ((int)wordsTableAdapter.WordExists(txtNewWord.Text) > 0)
                {
                    if ((int)wordsTableAdapter.WordAndRemainingExists(txtNewWord.Text, true)>0)
                        MessageBox.Show("The word \"" + txtNewWord.Text + "\" already exists!");
                    else
                    {
                        wordsTableAdapter.Update(txtNewMeaning.Text, true, txtNewWord.Text);
                        txtNewWord.Text = txtNewMeaning.Text = "";
                    }
                }
                else
                {
                    wordsTableAdapter.Insert(txtNewWord.Text, txtNewMeaning.Text, true);
                    txtNewWord.Text = txtNewMeaning.Text = "";
                }
            }
        }

        private void Settings_Click(object sender, EventArgs e)
        {
            SettingsForm settingsForm = new SettingsForm(Settings.Default.FormOpacity, Settings.Default.TimerInterval / 1000);

            if (settingsForm.ShowDialog(this) == DialogResult.OK)
            {
                this.Opacity = settingsForm.OpacitySetting / 100.0;
                timerChangeWord.Interval = settingsForm.TimerPeriodSetting * 1000;
                SaveSettings();
            }
        }

        private void RemoveCurrentWord(object sender, EventArgs e)
        {
            if (MessageBox.Show("Are you sure to remove word \"" + lblWord.Text + "\" permentaly?", "Warining",
                MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)
                 == DialogResult.Yes)
            {
                for (int i = 0; i < EntryList.Count; i++)
                    if (EntryList[i].Word == lblWord.Text)
                    {
                        wordsTableAdapter.Update(EntryList[i].Meaning, false, EntryList[i].Word);
                        EntryList.RemoveAt(i);
                        break;
                    }
                RefreshData();
                GetRandomWord(null, null);
            }
        }

        private void ShowHideForm(object sender, EventArgs e)
        {
            this.Visible = !this.Visible;
            if (this.Visible)
                this.Activate();
        }

        private void ExitApplication(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void MainForm_MouseDown(object sender, MouseEventArgs e)
        {
            isMouseDown = true;
            this.Cursor = Cursors.SizeAll;
            startDragPosition = e.Location;
        }

        private void MainForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMouseDown)
            {
                this.Location = new Point(
                    this.Location.X + (e.X - startDragPosition.X),
                    this.Location.Y + (e.Y - startDragPosition.Y)
                    );
            }
        }

        private void MainForm_MouseUp(object sender, MouseEventArgs e)
        {
            isMouseDown = false;
            this.Cursor = Cursors.Default;
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;
                this.Visible = false;
            }
            else
            {
                SaveSettings();
            }
        }

        private void SaveSettings()
        {
            Settings.Default.FormLocation = this.Location;
            Settings.Default.FormOpacity = (int)(this.Opacity * 100);
            Settings.Default.Save();
        }

        private void btnCloseAddNewWord_Click(object sender, EventArgs e)
        {
            HeadControlsPanel.Visible = WordsPanel.Visible = true;
            AddNewWordPanel.Visible = false;
            RefreshData();
            timerChangeWord.Start();
        }

        private void ShowAddPanel(object sender, EventArgs e)
        {
            HeadControlsPanel.Visible = WordsPanel.Visible = false;
            AddNewWordPanel.Visible = true;
            timerChangeWord.Stop();
        }

        private void GetRandomWord(object sender, EventArgs e)
        {
            timerChangeWord.Stop();
            SwitchMeaningOnOff(false);

            if(EntryList.Count>0)
            {
                int index = EntryList.IndexOf(currentEntry);
                if (index == EntryList.Count - 1)
                    index = 0;
                else
                    index++;
                currentEntry = EntryList[index];
            }
            else
            {
                currentEntry = WordEntry.Empty;
            }


            lblWord.Text = currentEntry.Word;

            timerChangeWord.Start();
        }

        private void btnPreviousWord_Click(object sender, EventArgs e)
        {
            timerChangeWord.Stop();
            SwitchMeaningOnOff(false);
            if (EntryList.Count > 0)
            {
                int index = EntryList.IndexOf(currentEntry);
                if (index == 0)
                    index = EntryList.Count - 1;
                else
                    index--;
                currentEntry = EntryList[index];
                lblWord.Text = currentEntry.Word;
                //lblMeaning.Text = currentEntry.Meaning;
            }
            timerChangeWord.Start();
        }

        private void notifyIcon_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                ShowHideForm(sender, e);
        }

        private void lblMeaning_Click(object sender, EventArgs e)
        {
            SwitchMeaningOnOff(lblMeaning.ForeColor == Color.FromName(Resources.HiddenMeaningColor));
        }

        private void SwitchMeaningOnOff(bool on)
        {
            if (on)
            {
                lblMeaning.Text = currentEntry.Meaning;
                lblMeaning.ForeColor = Color.Black;
            }
            else
            {
                lblMeaning.Text = Resources.TextInHiddenMeaning;
                lblMeaning.ForeColor = Color.FromName(Resources.HiddenMeaningColor);
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            StringBuilder str = new StringBuilder(Resources.About);
            str.Append("\nVersion: " + Application.ProductVersion);
            lock (wordsTableAdapter)
            {
                str.Append("\nTotal words count: " + wordsTableAdapter.GetTotalCount().ToString());
                str.Append("\nReminded words count: " + wordsTableAdapter.GetRemindedCount().ToString());
            }
            MessageBox.Show(str.ToString());
        }

        private void btnSayIt_Click(object sender, EventArgs e)
        {
            string text;
            if (sender == btnReminderSayIt)
                text = lblWord.Text;
            else if (sender == btnDicSayIt)
                text = lblSuggestedWord.Text;
            else
                throw new Exception();

            voice.Speak(text, SpeechVoiceSpeakFlags.SVSFlagsAsync | SpeechVoiceSpeakFlags.SVSFDefault);
        }

        private void comboWordSuggestion_TextChanged(object sender, EventArgs e)
        {
            #region Old
            //ComboBox senderCombo = sender as ComboBox;
            //db.WordsDataTable suggestedTable;
            //try
            //{
            //    suggestedTable = wordsTableAdapter.GetDataByTopCount(senderCombo.Text + "%");
            //}
            //catch (Exception ex)
            //{
            //    throw ex;
            //}
            //if (suggestedTable.Rows.Count > 0)
            //{
            //    if (sender == txtDicSearchWord)
            //    {
            //        lblSuggestedWord.Text = (string)suggestedTable.Rows[0]["Word"];
            //        txtSearchResult.Text = (string)suggestedTable.Rows[0]["Meaning"];
            //    }
            //    else if (sender == txtNewWord)
            //    {
            //        lblAddNewTextSuggestion.Text = (string)suggestedTable.Rows[0]["Word"];
            //        txtNewMeaning.Text = (string)suggestedTable.Rows[0]["Meaning"];
            //    }


            //    string[] words = new string[suggestedTable.Rows.Count];
            //    for (int i = 0; i < suggestedTable.Rows.Count; i++)
            //    {
            //        words[i] = (string)suggestedTable.Rows[i]["Word"];
            //    }

            //    senderCombo.SuspendLayout();
            //    senderCombo.Items.Clear();
            //    senderCombo.Items.AddRange(words);
            //    senderCombo.Select(senderCombo.Text.Length, 0);
            //    senderCombo.ResumeLayout();
            //}
            //else
            //{
            //    if (sender == txtNewWord)
            //    {
            //        lblAddNewTextSuggestion.Text = txtNewMeaning.Text = "";
            //    }
            //}
            #endregion

            if (suggestionThread != null && (suggestionThread.ThreadState == ThreadState.Running || suggestionThread.ThreadState == ThreadState.WaitSleepJoin))
            {
                suggestionThread.Abort();
            }
            suggestionThread = new Thread(new ParameterizedThreadStart(RunSuggestion));
            ComboBox senderCombo = sender as ComboBox;
            suggestionThread.Start(senderCombo.Text);
        }

        private void txtDicSearchWord_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        delegate void DelUpdateUI(WordEntryCollection words);
        private void UpdateUI(WordEntryCollection words)
        {
            ComboBox currentCombo;
            if (tabControl.SelectedTab == ReminderTabPage)
            {
                if (words.Count > 0)
                {
                    lblAddNewTextSuggestion.Text = words[0].Word;
                    txtNewMeaning.Text = (string)words[0].Meaning;
                }
                currentCombo = txtNewWord;
            }
            else if (tabControl.SelectedTab == dictionaryTabPage)
            {
                if (words.Count > 0)
                {
                    lblSuggestedWord.Text = words[0].Word;
                    txtSearchResult.Text = words[0].Meaning;
                }
                currentCombo = txtDicSearchWord;
            }
            else
                return;

            currentCombo.SuspendLayout();
            currentCombo.Items.Clear();
            foreach (WordEntry item in words)
            {
                currentCombo.Items.Add(item.Word);
            }
            currentCombo.Select(currentCombo.Text.Length, 0);
            currentCombo.ResumeLayout();
            if (words.Count == 0)
            {
                if (tabControl.SelectedTab == ReminderTabPage)
                {
                    lblAddNewTextSuggestion.Text = txtNewMeaning.Text = "";
                }
            }
        }

        private void RunSuggestion(object objWord)
        {
            try
            {
                Thread.Sleep(500);
                WordEntryCollection suggestedWords = new WordEntryCollection();
                string word = (string)objWord;
                if (!string.IsNullOrEmpty(word))
                {
                    db.WordsDataTable suggestedTable;
                    lock (wordsTableAdapter)
                    {
                        suggestedTable = wordsTableAdapter.GetDataByTopCount(word + "%");
                    }
                    for (int i = 0; i < suggestedTable.Rows.Count; i++)
                    {
                        suggestedWords.Add((string)suggestedTable.Rows[i]["Word"], (string)suggestedTable.Rows[i]["Meaning"]);
                    }
                }
                this.Invoke(new DelUpdateUI(UpdateUI), suggestedWords);
                    
                    
            }
            catch (ThreadAbortException)
            {
                return;
            }
        }

        private void txtNewWord_Enter(object sender, EventArgs e)
        {
            this.AcceptButton = btnAddNewWord;
        }

        private void txtNewWord_Leave(object sender, EventArgs e)
        {
            this.AcceptButton = null;
        }
    }
}
